package winOrDie.Sound.Voice;

import java.io.ByteArrayInputStream;
import java.math.BigInteger;

public class WAC {

	/**
	 * retorna un String con la cadena Hexadecimal
	 * @param buffer cadena byte[]
	 * @param vista true para verlo en modo vista previa, con espacios entre cada byte
	 * @return
	 */
	public static String byteToHex(byte[] buffer, boolean vista){
		String resultado=""; 
        ByteArrayInputStream input = new ByteArrayInputStream(buffer); 
        String cadAux; 
        int leido = input.read(); 
        while(leido != -1) 
        { 
                cadAux = Integer.toHexString(leido); 
                if(cadAux.length() < 2) //Hay que a�adir un 0 
                        resultado += "0";
                resultado += cadAux;
                leido = input.read();
                
                if ((vista) && (leido != -1)) resultado += "-";
        } 
        return resultado;
	}
	
	/**
	 * retorna una cadena byte[]
	 * @param bufferHex con String de los hexadecimales bien ordenado con espacios
	 * @return
	 */
	public static byte[] hexToByte(String bufferHex){
		byte[] bts = new BigInteger(bufferHex, 16).toByteArray();
		
		if (bts.length < bufferHex.length()/2){
			
			byte[] bts2 = new byte[bufferHex.length()/2];
            
			for (int i = 0; i < bts.length; i++)
				bts2[bts2.length - i - 1] = bts[bts.length - i - 1];
			
			// pone los ceros que faltan delante
			for (int i = 0; i < (bts2.length - bts.length)%3 ; i++) {
				bts2[i] = 0;
			}
			
			return bts2;
		}else if (bts.length > bufferHex.length()/2){
			byte[] bts2 = new byte[bufferHex.length()/2];
            
			for (int i = 0; i < bts2.length; i++)
				bts2[i] = bts[i + 1];
			
			return bts2;
		}
		
		return bts;
	}
	
	/**
	 * WAC Layer 2 en pruebas
	 * elimina muestras residualmente bajas
	 * @param buffer
	 * @return
	 */
	public static byte[] light(byte[] buffer){
		String bufferStr[] = byteToHex(buffer, true).split("-");
		String salida = "";
		int n = 0;
		
		for (int i = 0; i < bufferStr.length; i++) {
			n = 0;
			
			if (bufferStr[i].equals("01") || bufferStr[i].equals("02"))salida += "00";
			else salida += bufferStr[i];
			
//			System.out.println(n + " " + salida);
		
		}
		
		return hexToByte(salida);		
	}
	
	/**
	 * codifica con el protocolo WAC WinOrDie Audio Codec
	 * @param buffer
	 * @return
	 */
	public static byte[] compress(byte[] buffer){
		String bufferStr[] = byteToHex(buffer, true).split("-");
		String salida = "";
		int n = 0;
		
		for (int i = 0; i < bufferStr.length; i++) {
			n = 0;
			salida += bufferStr[i];
			if (bufferStr[i].equals("00")){
				while ((bufferStr.length > i) && (bufferStr[i].equals("00"))) {
					n++;
					i++;
				}
			}else if (bufferStr[i].equals("ff")){
				while ((bufferStr.length > i) && (bufferStr[i].equals("ff"))) {
					n++;
					i++;
				}
			}
			
			if (n > 15 ){
				salida += ""+Integer.toHexString(n);
				i--;
			}else if (n > 0){
				salida += "0"+Integer.toHexString(n);
				i--;
			}
			
//			System.out.println(n + " " + salida);
		
		}
		
		return hexToByte(salida);
	}
	
	/**
	 * decodifica el protocolo WAC WinOrDie Audio Codec
	 * @param buffer
	 * @return
	 */
	public static byte[] uncompress(byte[] buffer){
		String bufferStr[] = byteToHex(buffer, true).split("-");
		String salida = "";
		
		for (int i = 0; i < bufferStr.length; i++) {
			salida += bufferStr[i];
			
			if ((i != bufferStr.length - 1) && bufferStr[i].equals("00")){
				i++;
				for (int j = 0; j < Integer.parseInt(bufferStr[i], 16) - 1; j++) {
					salida += "00";
				}
			}else if ((i != bufferStr.length - 1) && bufferStr[i].equals("ff")){
				i++;
				for (int j = 0; j < Integer.parseInt(bufferStr[i], 16) - 1; j++) {
					salida += "ff";
				}
			}
			
		}
		
		return hexToByte(salida);
	}
	
}
